package com.siyu.rehearsal.controller;


import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.siyu.basedata.modelparam.domain.ModelParam;
import com.siyu.basedata.plan.domain.Plan;
import com.siyu.basedata.plan.service.IPlanService;
import com.siyu.basedata.xajresult.service.IXajResultService;
import com.siyu.common.core.controller.BaseController;
import com.siyu.common.core.domain.AjaxResult;
import com.siyu.rehearsal.dto.*;
import com.siyu.rehearsal.previewnd.domain.PreviewNd;
import com.siyu.rehearsal.previewnd.service.IPreviewNdService;
import com.siyu.rehearsal.previewpfbase.domain.PreviewPFbase;
import com.siyu.rehearsal.previewpparameters.domain.PreviewPParameters;
import com.siyu.rehearsal.previewpparameters.service.IPreviewPParametersService;
import com.siyu.rehearsal.service.PlanDispatchService;
import com.siyu.rehearsal.vo.PptnRResultVo;
import com.siyu.rehearsal.vo.PreviewInspectVo;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
import java.util.stream.Stream;


@RestController
@RequestMapping("/rehearsal/dispatch")
public class PlanDispatchController extends BaseController {
    @Autowired
    private PlanDispatchService planDispatchService;

    @Autowired
    private IXajResultService xajResultService;

    @Autowired
    private IPlanService planService;

    @Autowired
    private IPreviewNdService previewNdService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private IPreviewPParametersService previewPParametersService;

    /**
     * 预演计算
     *
     * @param planCalculateDto
     * @return
     * @throws Exception
     */
    @PostMapping("/plan/calculate")
    public AjaxResult getCalculateResult(@RequestBody PlanCalculateDto planCalculateDto) throws Exception {

        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        // 尝试设置锁，并设置过期时间为60秒
        Boolean lock = ops.setIfAbsent("calculate", "calculatelock", Duration.ofSeconds(1800));
        if (lock != null && lock) {
            try {
                Object calculateResult = planDispatchService.getCalculateResult(planCalculateDto);
                redisTemplate.delete("calculate");
                return AjaxResult.success(calculateResult);
            } catch (Exception e) {
                e.printStackTrace();
                redisTemplate.delete("calculate");
                return AjaxResult.error("计算出错!");
            }
        } else {
            return AjaxResult.warn("正在计算中!");
        }

    }

    /**
     * 预演方案保存
     *
     * @param planPreviewSaveDto
     * @return
     */
    @PostMapping("/plan/save")
    @Transactional
    public AjaxResult savePlanPreview(@RequestBody PlanPreviewSaveDto planPreviewSaveDto) {
        try {
            String result = planDispatchService.savePlanPreview(planPreviewSaveDto);
            if (result != null) {
                return AjaxResult.success(result);
            } else {
                return AjaxResult.success("方案保存成功!");
            }
        } catch (Exception e) {
            return AjaxResult.error("方案保存失败!");
        }
    }


    /**
     * 降雨过程查询
     *
     * @param planDispatchDto
     * @return
     */
    @PostMapping("/plan/rainfall")
    public AjaxResult getOpenPlan(@RequestBody PlanDispatchDto planDispatchDto) throws Exception {
        PptnRResultVo pptnRResultVo = planDispatchService.getRain(planDispatchDto);
        return AjaxResult.success(pptnRResultVo);
    }

    /**
     * 查询情景降雨数据(多)
     * @param id
     * @return
     */
    @GetMapping("/plan/false")
    public AjaxResult getFalse(@RequestParam("id")String id){
        try {
            Object object = planDispatchService.getFalse(id);
            return AjaxResult.success(object);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询失败!");
        }
    }



    /**
     * 调度参数查询
     *
     * @param rscd
     * @return
     */
    @GetMapping("/plan/parameter")
    public AjaxResult getDispatchParameter(@RequestParam("rscd") String rscd) {
        Object object = planDispatchService.getDispatchParameter(rscd);
        return AjaxResult.success(object);
    }

    /**
     * 情景方案查询
     */
    @GetMapping("/plan/scene")
    public AjaxResult getScene(@RequestParam("rscd")String rscd) {
        QueryWrapper<Plan> planQueryWrapper = new QueryWrapper<Plan>();
        planQueryWrapper.select("id", "plan_name")
                .eq("rscd", rscd)
                .eq("pre_type", "情景");
        List<Plan> list = planService.list(planQueryWrapper);
        return AjaxResult.success(list);
    }

    /**
     * 验证方案数据是否存在/不存在则不能可视化
     *
     * @param id
     * @return
     */
    @GetMapping("/plan/inspect")
    public AjaxResult getByPlanId(@RequestParam("id") String id) {
        // 创建LambdaQueryWrapper实例
        Plan plan = planService.getOne(new LambdaQueryWrapper<Plan>().select(Plan::getId,Plan::getRscd,Plan::getPlanType).eq(Plan::getId, id).eq(Plan::getPreType, "预演"));

        if (plan == null) {
            return AjaxResult.warn("方案未保存!");
        }
        PreviewInspectVo previewInspectVo = new PreviewInspectVo();
        BeanUtil.copyProperties(plan,previewInspectVo);

        if (plan.getPlanType().equals("瞬间溃坝") || plan.getPlanType().equals("逐渐溃坝")){
            QueryWrapper<PreviewPParameters> previewPParametersQueryWrapper = new QueryWrapper<>();
            previewPParametersQueryWrapper.eq("rscd", plan.getRscd());
            List<PreviewPParameters> previewPParameters = previewPParametersService.list(previewPParametersQueryWrapper);
            previewInspectVo.setPreviewPParameters(previewPParameters);
        }

        return AjaxResult.success(previewInspectVo);
    }

    /**
     *情景流量数据导入
     * @param planSightDto
     * @return
     */
    @PostMapping("/plan/sight")
    public AjaxResult saveSight(@RequestBody PlanSightDto planSightDto) {
        return planDispatchService.saveSight(planSightDto);
    }

    /**
     * 情景方案删除
     * @param id
     */
    @DeleteMapping("/plan/deleteq")
    @Transactional
    public AjaxResult deleteq(@RequestParam("id") String id) {
        try {
            planService.deletePlanById(id);
            QueryWrapper<PreviewNd> previewNdQueryWrapper = new QueryWrapper<>();
            previewNdQueryWrapper.eq("plan_id", id);
            previewNdService.remove(previewNdQueryWrapper);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("删除失败!");
        }
        return AjaxResult.success("删除成功!");
    }

    /**
     * 溃坝流量数据查询
     * @param rscd
     * @param preType
     * @return
     */
    @GetMapping("/plan/dbreak")
    public AjaxResult dbreak(@RequestParam("rscd")String rscd,
                             @RequestParam("preType")String preType){
        return planDispatchService.dbreak(rscd, preType);
    }

    /**
     * 预演结构化数据查询
     * @param rscd
     * @return
     */
    @GetMapping("/plan/fbase")
    public AjaxResult fbase(@RequestParam("rscd") String rscd){
        return planDispatchService.getfbase(rscd);
    }

    /**
     * 预演结构化数据查询
     * @param previewPFbases
     * @return
     */
    @PostMapping("/plan/upfbase")
    public AjaxResult upfbase(@RequestBody List<PreviewPFbase> previewPFbases){
        return planDispatchService.upfbase(previewPFbases);
    }


    public static void main(String[] args) {
        String pathStr = "./modeldata";
        Path directory = Paths.get(pathStr);

        try (Stream<Path> paths = Files.walk(directory)) {
            paths.filter(Files::isRegularFile)
                    .filter(p -> p.getFileName().toString().contains("max_wDepth"))
                    .forEach(p -> {
                        try {
                            String content = new String(Files.readAllBytes(p));
                            JSONObject jsonObject = JSONObject.parseObject(content, JSONObject.class);
                            JSONArray jsonArray = JSONObject.parseObject(jsonObject.get("features").toString(), JSONArray.class);
                            int size = jsonArray.size();
                            double i = size * 900 / 1000000.0;
                            Integer DN = 0;
                            for (Object o : jsonArray) {
                                JSONObject features = JSONObject.parseObject(o.toString(), JSONObject.class);
                                JSONObject properties = JSONObject.parseObject(features.get("properties").toString(), JSONObject.class);
                                Integer dn = JSONObject.parseObject(properties.get("DN").toString(), Integer.class);
                                if (dn > DN) {
                                    DN = dn;
                                }
                            }
                            double v = DN / 100.0;
                            double depth = Math.round(v * 10.0) / 10.0;

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }

        final Optional<Path>[] largestFile = new Optional[]{null};
        final long[] maxFileSize = {0};

        try (Stream<Path> paths = Files.walk(directory)) {
            paths.filter(Files::isRegularFile)
                    .filter(p -> p.getFileName().toString().contains("-") && p.toString().endsWith(".geojson"))
                    .forEach(p -> {
                        try {
                            long fileSize = Files.size(p);
                            if (fileSize > maxFileSize[0]) {
                                maxFileSize[0] = fileSize;
                                largestFile[0] = Optional.of(p);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });

            if (largestFile[0].isPresent()) {
                System.out.println("The largest GeoJSON file is: " + largestFile[0].get());
            } else {
                System.out.println("No GeoJSON files found with '-' in their names.");
            }
            Path path = Paths.get(largestFile[0].get().toString());
            String fileName = path.getFileName().toString();

            // 分割文件名，去除扩展名
            String[] parts = fileName.split("\\.(?=[^\\.]+$)");
            String baseName = parts[0];

            // 再次分割基础文件名，去除前缀
            String[] dateParts = baseName.split("_");
            String dateTimePart = dateParts[1]+" "+ dateParts[2];
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm");
            Date parse = sdf.parse(dateTimePart);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 预演计算
     */
    @PostMapping("/model/calculation")
    public AjaxResult calculation(@RequestBody PreviewForTDto previewForTDto) throws Exception {
        //调用一维计算,获取断面流量数据结果
//        TopologyDto topologyDto = new TopologyDto();
//        topologyDto.setPrs(previewForTDto.getPrs());
//        topologyDto.setTms(previewForTDto.getTms());
//        topologyDto.setParamMap(previewForTDto.getParamMap());
//        topologyDto.setStartZ(previewForTDto.getStartZ());
//        LinkedHashMap<String, HashMap<String, Object>> topology = predictService.topology(topologyDto);
//        return previewService.calculation(previewForTDto,topology);
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        // 尝试设置锁，并设置过期时间为60秒
        Boolean lock = ops.setIfAbsent("calculate", "calculatelock", Duration.ofSeconds(7200));
        if (lock != null && lock) {
            try {
                HashMap<String, Object> calculation = planDispatchService.calculation(previewForTDto);

                return AjaxResult.success(calculation);
            } catch (Exception e) {
                e.printStackTrace();
                redisTemplate.delete("calculate");
                return AjaxResult.error("计算出错!");
            }
        } else {
            return AjaxResult.warn("业务模型上一次计算未完成，请稍后再试！");
        }
    }
}
